# Create your views here.
import datetime
from collections import Counter

from django_redis import get_redis_connection
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework import status

from goods.filters import GoodsFilter, GoodsSearchFilter
from goods.serializers import GoodsSerializer, CategorySerializer, BannerSerializer, HotWordsSerializer, \
    GoodsSearchSerializer, GoodsIndexSerializer, DiscountPackageSerializer, SearchAdSerializer, \
    NewGoodsSerializer, HotGoodsSerializer, HighpointGoodsSerializer, CategoryIndexSerializer, GoodsAttributeSerializer, \
    GoodsColorSerializer
from .models import Goods, GoodsCategory, Banner, HotSearchWords, DiscountPackage, SearchAd, GoodsAttribute
from rest_framework import mixins
from rest_framework import viewsets
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework_extensions.cache.mixins import CacheResponseMixin
from .serializers import GoodsElasticsearchIndexSerializer
from drf_haystack.viewsets import HaystackViewSet


# 设置登录与未登录限速
# from rest_framework.throttling import UserRateThrottle, AnonRateThrottle


# 商品列表分页类-
class GoodsPagination(PageNumberPagination):
    page_size = 12
    # page_size = 2
    # 向后台要多少条
    page_size_query_param = 'page_size'
    # 定制多少页的参数
    page_query_param = "page"
    max_page_size = 100


class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """商品详情页"""
    # throttle_classes = (UserRateThrottle, AnonRateThrottle)
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination
    queryset = Goods.objects.filter(is_delete=False)

    # 设置列表页的单独auth认证也就是不认证
    # authentication_classes = (TokenAuthentication,)

    # 设置三大常用过滤器之DjangoFilterBackend, SearchFilter
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    # 设置排序 按销量 按价格
    ordering_fields = ('sold_num', 'shop_price')
    # 设置filter的类为我们自定义的类
    filter_class = GoodsFilter

    # 设置我们的search字段
    search_fields = ('name', 'goods_brief', 'goods_desc')

    # 设置我们需要进行过滤的字段
    filter_fields = ('name', 'shop_price')

    # 商品点击数+1
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.views_amount += 1
        instance.save()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class GoodColorViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """商品颜色"""
    queryset = GoodsAttribute.objects.filter(is_delete=False)
    serializer_class = GoodsColorSerializer
    lookup_field = "goods_id"

    def get_queryset(self):
        """获取路由上的goods_id值"""
        try:
            goods_id = int(self.kwargs.get("goods_id"))
        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        queryset = GoodsAttribute.objects.filter(goods=goods_id)
        return queryset

    def retrieve(self, request, *args, **kwargs):
        """指定返回的商品属性"""
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


# luo
class GoodsElasticSearchViewSet(HaystackViewSet):
    """商品搜索视图集"""
    # 指定索引模型类
    index_models = [Goods]
    pagination_class = GoodsPagination

    # 指定搜索结果序列化时所使用的序列化器类
    serializer_class = GoodsElasticsearchIndexSerializer

    def list(self, request, *args, **kwargs):
        # 重写，存储用户的搜索词
        keywords = request.query_params.get('text')
        # 搜索词存入redis
        redis_con = get_redis_connection('search_key')
        if redis_con.llen('keywords_list') <= 10000:
            redis_con.lpush('keywords_list', keywords)
        else:
            redis_con.rpop("keywords_list")
            redis_con.lpush('keywords_list', keywords)
        return super().list(request)


class GoodsAttributeViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """商品属性"""
    queryset = GoodsAttribute.objects.filter(is_delete=False)
    serializer_class = GoodsAttributeSerializer

    def list(self, request, *args, **kwargs):
        goods_id = request.query_params.get("goods_id")
        color = request.query_params.get("color")
        if goods_id == None or color == None:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        queryset = GoodsAttribute.objects.filter(goods=goods_id, color=color)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """获取轮播图列表"""
    queryset = Banner.objects.filter(is_delete=False)
    serializer_class = BannerSerializer


class CategoryBarViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """首页导航栏商品类别显示"""
    queryset = GoodsCategory.objects.filter(is_delete=False)
    serializer_class = CategorySerializer


class CategoryViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """首页商品类别显示及该类别下的商品显示，最多6个"""
    serializer_class = GoodsIndexSerializer
    queryset = ''  # 定义为空，避免浏览器打开接口报错

    def list(self, request, *args, **kwargs):
        try:
            category_index = GoodsCategory.objects.filter(is_index=True, is_delete=False)
        except Exception as e:
            return Response(status=status.HTTP_204_NO_CONTENT)
        category_index_serializer = []
        for category in category_index:
            serializer_category = CategoryIndexSerializer(category, context={'request': request})
            goods_index = Goods.objects.filter(goods_status=1, category=category,is_delete=False)[:6]
            serializer_goods = self.get_serializer(goods_index, many=True)
            result = {
                "category": serializer_category.data,
                "goods": serializer_goods.data,
            }
            category_index_serializer.append(result)
        count = len(category_index_serializer)
        category_index_serializer.insert(0, {"count": count})
        return Response(category_index_serializer)


class NewGoodsViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """新品专享"""
    serializer_class = NewGoodsSerializer
    pagination_class = GoodsPagination
    queryset = Goods.objects.filter(is_new=True, goods_status=1, is_delete=False).order_by('-create_time')
    ordering_fields = ('sold_num', 'shop_price')


class HotGoodsViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """热销榜"""
    serializer_class = HotGoodsSerializer
    pagination_class = GoodsPagination
    queryset = Goods.objects.filter(is_delete=False,is_hot=True, goods_status=1).order_by('-start_time')
    ordering_fields = ('sold_num', 'shop_price')


class HighpointGoodsViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,
                            viewsets.GenericViewSet):
    """高端榜"""
    serializer_class = HighpointGoodsSerializer
    pagination_class = GoodsPagination
    queryset = Goods.objects.filter(is_delete=False,is_highpoint=True, goods_status=1).order_by('-start_time')
    ordering_fields = ('sold_num', 'shop_price')


class SearchAdViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """搜索框下方广告"""
    queryset = SearchAd.objects.filter(is_delete=False)
    serializer_class = SearchAdSerializer


class HotSearchsViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """获取热搜词列表"""
    queryset = HotSearchWords.objects.all().order_by("-index")
    serializer_class = HotWordsSerializer

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        if queryset:
            # 如果后台手动设置热搜词，优先取后台的
            return super().list(request)
        else:
            # 如果后台未设置热搜词，则取用户输入的热搜词
            redis_con = get_redis_connection('search_key')
            keywords_list = [keywords.decode('utf8') for keywords in redis_con.lrange('keywords_list', 0, -1)]
            # 统计词频
            result = Counter(keywords_list)
            # 排序
            sort_list = sorted(result.items(), key=lambda x: x[1], reverse=True)[0:8]
            return_data = []
            if sort_list:
                index = 0
                for li in sort_list:
                    index += 1
                    result = {
                        'id': index,
                        'keywords': li[0],
                        'index': index
                    }
                    return_data.append(result)
        return Response(return_data)


class ViewMoreViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """查看更多"""
    queryset = Goods.objects.filter(is_delete=False)
    pagination_class = GoodsPagination
    serializer_class = GoodsSearchSerializer
    lookup_field = 'category_id'

    def list(self, request, *args, **kwargs):
        """不带参数请求返回空，防止报错"""
        return Response(status=status.HTTP_501_NOT_IMPLEMENTED)

    def get_queryset(self):
        """获取路由上的category_id值"""
        try:
            category_id = int(self.kwargs.get("category_id"))
        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        queryset = Goods.objects.filter(category=category_id, goods_status=1,is_delete=False)
        return queryset

    def retrieve(self, request, *args, **kwargs):
        """指定返回某一个分类下的商品,并做分页"""
        queryset = self.get_queryset()
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class DiscountPackageViewset(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """商品详情页优惠套餐显示"""
    queryset = DiscountPackage.objects.filter(is_valid=True, is_delete=False)
    serializer_class = DiscountPackageSerializer
    pagination_class = GoodsPagination
    lookup_field = 'goods_id'

    def get_queryset(self):
        """获取路由上的goods_id值"""
        try:
            goods_id = int(self.kwargs.get("goods_id"))
        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        queryset = DiscountPackage.objects.filter(goods=goods_id, is_valid=True)
        return queryset

    def retrieve(self, request, *args, **kwargs):
        """指定返回某一个商品的套餐组合"""
        today = datetime.date.today()
        queryset = self.get_queryset()
        # 如果套餐中有一个或多个商品下架，那么该套餐失效
        for i in queryset:
            for j in i.goods.all():
                # 如果当前时间在套餐的有效期内，那么该套餐生效
                if i.start_time <= today <= i.end_time:
                    i.is_valid = True
                    i.save()
                # 如果套餐中有一个或多个商品下架或者超出活动时间，那么该套餐失效
                if j.goods_status == 0 or (today >= i.end_time):
                    i.is_valid = False
                    i.save()
        # 修改套餐属性后重新获取
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class DiscountPriceViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    def list(self, request, *args, **kwargs):
        """返回套餐总价"""
        attribute_list = request.data.get("attribute_list")
        discountpackage_id = request.data.get("discountpackage_id")
        if not all([attribute_list, discountpackage_id]): return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
        discount = DiscountPackage.objects.filter(id=discountpackage_id, is_delete=False).first()
        if discount:
            saved_at_most = discount.saved_at_most
            original_price = 0
            for attribute in attribute_list:
                goods_attribute = GoodsAttribute.objects.filter(id=attribute).first()
                if goods_attribute: original_price += goods_attribute.price
            total_price = original_price - saved_at_most
            return Response(data={"total_price": total_price, "saved_at_most": saved_at_most})
        else:
            return Response(data={'msg': '套餐已失效/下架'}, status=status.HTTP_423_LOCKED)
